/*单例模式保证一个类仅有一个实例，并提供一个访问它的全局访问点*/
#include <utility>
#include <stdexcept>
#include <iostream>
#include <string>

using std::cout;
using std::endl;

template<typename T>
class Singleton{
    public:
        template<typename... Args>
            static T * Instance(Args&&... args)
            {
                if(m_pInstance == nullptr)
                    m_pInstance = new T(std::forward<Args>(args)...);
                return m_pInstance;
            }
        static T * GetInstance()
        {
            if(m_pInstance == nullptr)
                throw std::logic_error("the instance is not init, please initialize the instance frist");
            return m_pInstance;
        }
        static void DestroyInstance()
        {
            delete m_pInstance;
            m_pInstance = nullptr;
        }
    private:
        Singleton(void);
        virtual ~Singleton(void);
        Singleton(const Singleton&);
        Singleton & operator=(const Singleton&);
        static T * m_pInstance;
};

template<class T> 
T* Singleton<T>::m_pInstance = nullptr; //其实还是 类型+全局作用符+静态成员变量。 不同的是，传入了外部模板类型


struct A{
    A(const std::string& ){cout << "lavue" << endl;}
    A(std::string && x) { cout << "rvalue" << endl; }
};

struct B{
    B(const std::string& ){cout << "lavue" << endl;}
    B(std::string && x) { cout << "rvalue" << endl; }
};

class C{
    public:
        C(int x, double y) : a(x), b(y){}
        void Fun(){cout << a << "\t" << b<< endl;}
    private:
        int a;
        double b;
};

int main(void)
{
    std::string str = "BB";
    Singleton<A>::Instance(str);
    Singleton<B>::Instance(std::move(str));
    str.push_back('A');

    cout << str << endl;
    

    //Singleton<C>::Instance(1, 3.14); //如果没有这场，在执行时会被abort
    Singleton<C>::GetInstance()->Fun();

    Singleton<A>::DestroyInstance();
    Singleton<B>::DestroyInstance();
    Singleton<C>::DestroyInstance();
    return 0;
}
